package su.samcom.calc.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import su.samcom.calc.service.util.CalculatorUtil;
import su.samcom.calc.controller.form.CalculatorForm;
import su.samcom.calc.controller.validator.CalculatorFormValidator;
import su.samcom.calc.exception.RouteNotFoundException;
import su.samcom.calc.model.entity.Country;
import su.samcom.calc.model.entity.Location;
import su.samcom.calc.model.entity.Price;
import su.samcom.calc.service.CalculatorServiceImpl;
import su.samcom.calc.service.LocationService;
import su.samcom.calc.service.CalculatorService;
import su.samcom.calc.service.record.LocationRecord;
import su.samcom.calc.service.util.CargoParameters;

import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: Владислав
 * Date: 28.11.13
 * Time: 23:48
 * To change this template use File | Settings | File Templates.
 */
@Controller
@RequestMapping(value = "/calculator")
//@SessionAttributes("priceForm")
public class CalculatorController {

    public final static int MAX_LOCATIONS = 10;

    /*@Autowired
    private CalculatePriceForm calculatePriceForm;*/

    @Autowired
    private CalculatorService calculatorService;
    @Autowired
    private LocationService locationService;

    @ModelAttribute(value = "priceForm")
    public CalculatorForm createCalculatorForm() {
        return new CalculatorForm();
    }

    @RequestMapping(method = RequestMethod.GET)
    public String calculator(@ModelAttribute CalculatorForm calculatorForm, Model model){
        List<Country> countries = locationService.getCountries();
        model.addAttribute("countries", countries);
        return "calculator.calculator";
    }

    @RequestMapping(value = "/locations", method = RequestMethod.POST)
    public @ResponseBody LocationRecord[] getLocationRecords(@RequestParam String locationName, @RequestParam Long countryId, Model model){
        List<LocationRecord> locationRecords = locationService.getLikeLocations(locationName, countryId);
        if(locationRecords.size() > MAX_LOCATIONS){
            locationRecords = locationRecords.subList(0, MAX_LOCATIONS);
        }
        return locationRecords.toArray(new LocationRecord[locationRecords.size()]);
    }

    @RequestMapping(value = "/cargo-parameters", method = RequestMethod.POST)
    public @ResponseBody CargoParameters getMinCargoParameters(@RequestParam CalculatorServiceImpl.CargoType cargoType){
        if (cargoType == CalculatorServiceImpl.CargoType.GENERAL){
            return CalculatorUtil.MIN_GENERAL;
        } else if (cargoType == CalculatorServiceImpl.CargoType.SEPARATE){
            return CalculatorUtil.MIN_SEPARATE;
        }
        return null;
    }

    @RequestMapping(value = "/calculate", method = RequestMethod.POST)
    public String location(@ModelAttribute CalculatorForm calculatorForm, BindingResult bindingResult, Model model){
        List<Country> countries = locationService.getCountries();
        model.addAttribute("countries", countries);
        if(calculatorForm.getCargoType() != null){
            if (calculatorForm.getCargoType() == CalculatorServiceImpl.CargoType.GENERAL){
                model.addAttribute("minCargoParameters", CalculatorUtil.MIN_GENERAL);
            } else if (calculatorForm.getCargoType() == CalculatorServiceImpl.CargoType.SEPARATE){
                model.addAttribute("minCargoParameters", CalculatorUtil.MIN_SEPARATE);
            }

        }

        boolean validCargoParameters = CalculatorFormValidator.validateCargoParameters(calculatorForm, bindingResult, model);
        boolean validLocationFrom = CalculatorFormValidator.validateLocationFrom(calculatorForm, model);
        boolean validLocationTo = CalculatorFormValidator.validateLocationTo(calculatorForm, model);

        Location locationFrom = null;
        if(validLocationFrom){
            locationFrom = locationService.getLocation(calculatorForm.getLocationFrom(), calculatorForm.getCountryFromId());
            validLocationFrom = CalculatorFormValidator.validateLocationFrom(locationFrom, model);
        }

        Location locationTo = null;
        if(validLocationTo){
            locationTo = locationService.getLocation(calculatorForm.getLocationTo(), calculatorForm.getCountryToId());
            validLocationTo = CalculatorFormValidator.validateLocation(locationTo, model);
        }

        if (!validLocationFrom || !validLocationTo || calculatorForm.getCargoType() == null){
            return "calculator.calculator-form";
        }

        List<Price> prices;
        try{
            prices = calculatorService.getCargoPrices(locationFrom.getId(), locationTo.getId(), calculatorForm.getCargoType());
        }catch(RouteNotFoundException e){
            model.addAttribute(CalculatorFormValidator.COMMON_ERROR, "Выбранный маршрут не проинициализирован");
            return "calculator.calculator-form";
        }
        if(prices.size() < 2){
            model.addAttribute(CalculatorFormValidator.COMMON_ERROR, "Выбранный маршрут проинициализирован не полностью");
            return "calculator.calculator-form";
        }

        if (!validCargoParameters){
            return "calculator.calculator-form";
        }

        CargoParameters cargoParameters = new CargoParameters();
        cargoParameters.setCbm(calculatorForm.getCbm());
        cargoParameters.setLength(calculatorForm.getLength());
        cargoParameters.setWeight(calculatorForm.getWeight());
        double loadedPercent = CalculatorUtil.calculateLoadedPercent(cargoParameters, calculatorForm.getCargoType());
        int price = CalculatorUtil.calculatePrice(prices, loadedPercent);
        model.addAttribute("price", price);
        return "calculator.calculator-form";
    }
}
